using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Colman.Rpg.Connection;
using Colman.Rpg.Messaging;
using Colman.Rpg.Npc;

namespace Colman.Rpg.Battles
{
    /// <summary>
    /// The form that shows battles between either players or a player and monster.
    /// </summary>
    public partial class BattleForm : ConnectionAwareForm
    {
        /// <summary>
        /// Creates a new instance of <see cref="BattleForm" />.
        /// </summary>
        public BattleForm()
        {
            InitializeComponent();

            this.DialogResult = DialogResult.No;
        }

        #region Player Player { get; set; } (player)
        private Player player;

        /// <summary>
        /// Gets or sets the player's character.
        /// </summary>
        public Player Player
        {
            [System.Diagnostics.DebuggerStepThrough]
            get
            {
                return this.player;
            }
            [System.Diagnostics.DebuggerStepThrough]
            set
            {
                if (this.player != value)
                {
                    this.player = value;

                    this.playerSheet.DataSource = value;
                }
            }
        }
        #endregion

        #region Character Opponent { get; set; } (opponent)
        private Character opponent;

        /// <summary>
        /// Gets or sets the player's adversary.
        /// </summary>
        public Character Opponent
        {
            [System.Diagnostics.DebuggerStepThrough]
            get
            {
                return this.opponent;
            }
            [System.Diagnostics.DebuggerStepThrough]
            set
            {
                if (this.opponent != value)
                {
                    this.opponent = value;

                    this.opponentSheet.DataSource = value;

                    if (this.opponent is Monster)
                        this.battleGroundControl1.BattleType = Colman.Rpg.Controls.BattleType.Npc;
                    else
                        this.battleGroundControl1.BattleType = Colman.Rpg.Controls.BattleType.Pvp;
                }
            }
        }
        #endregion

        /// <summary>
        /// Called when a message is received from the server.
        /// </summary>
        /// <param name="sender">The object that raised the event.</param>
        /// <param name="e">The message arguments.</param>
        protected override void OnMessageReceived(object sender, MessageReceivedEventArgs e)
        {            
            base.OnMessageReceived(sender, e);
            
            FightResponse response = e.Message as FightResponse;

            if (response != null)
            {
                this.Player = response.Player;
                this.Opponent = response.Opponent;
                this.lblRound.Text = (Int32.Parse(this.lblRound.Text)+1).ToString();

                // Create transcript
                if (response.PlayerAction != FightActionType.Flee &&
                    response.OpponentAction != FightActionType.Flee)
                {
                    this.battleTranscript.Text = this.CreateTranscript(response) + Environment.NewLine + this.battleTranscript.Text;
                }

                this.battleGroundControl1.Animate(
                    (response.PlayerAction == FightActionType.Defend ? response.PlayerActionResult : 0),
                    (response.OpponentAction == FightActionType.Defend ? response.OpponentActionResult : 0),
                    (response.PlayerAction == FightActionType.Attack ? response.PlayerActionResult : 0),
                    (response.OpponentAction == FightActionType.Attack ? response.OpponentActionResult : 0));
            }
            else if (e.Message is PlayerWinsResponse)
            {
                PlayerWinsResponse winResponse = e.Message as PlayerWinsResponse;

                MessageBox.Show(this, "You win. Congratulations!" + Environment.NewLine +
                    "You have gained " + winResponse.GainedXP + " points of experience" +
                    (winResponse.GoldWon > 0 ? " and " + winResponse.GoldWon + " gold" : string.Empty) + "!",
                    this.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

                this.DialogResult = DialogResult.OK;
                this.Close();
            }
            else if (e.Message is PlayerLosesResponse)
            {
                MessageBox.Show("You have lost. Worry not - you will live to fight another day.");

                this.DialogResult = DialogResult.Cancel;
                this.Close();
            }
        }

        private string CreateTranscript(FightResponse response)
        {
            string transcript = string.Empty;

            switch (response.PlayerAction)
            {
                case FightActionType.Attack:
                    transcript = string.Format("You lunge at {0} with your {1} and hit for {2} points worth of damage!{3}",
                        response.Opponent.Name, response.Player.Weapon.Name, response.PlayerActionResult, Environment.NewLine);
                    break;
                case FightActionType.Defend:
                    transcript = string.Format("You cower under your {0} and gain {1} health points...{2}",
                        response.Player.Armor.Name, response.PlayerActionResult, Environment.NewLine);
                    break;
            }

            switch (response.OpponentAction)
            {
                case FightActionType.Attack:
                    transcript += string.Format("{0} lunges at you and hits for {1} points worth of damage!{2}",
                        response.Opponent.Name, response.OpponentActionResult, Environment.NewLine);
                    break;
                case FightActionType.Defend:
                    transcript += string.Format("{0} cowers, defending, and gains {1} health points...{2}",
                        response.Opponent.Name, response.OpponentActionResult, Environment.NewLine);
                    break;
            }

            return transcript;
        }

        private void btnAttack_Click(object sender, EventArgs e)
        {
            this.btnAttack.Enabled = false;
            this.btnDefend.Enabled = false;
            this.btnFlee.Enabled = false;
            ClientEndPoint.Instance.SendMessage(new FightRequest(FightActionType.Attack));
        }

        private void btnDefend_Click(object sender, EventArgs e)
        {
            this.btnAttack.Enabled = false;
            this.btnDefend.Enabled = false;
            this.btnFlee.Enabled = false;
            ClientEndPoint.Instance.SendMessage(new FightRequest(FightActionType.Defend));
        }

        private void btnFlee_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show(
                    this,
                    "Are you sure you wish to flee? It's just like losing, only your experience takes half the damage.",
                    this.Text,
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button2) == DialogResult.Yes)
            {
                ClientEndPoint.Instance.SendMessage(new FightRequest(FightActionType.Flee));
            }
        }

        private void battleGroundControl1_AnimationComplete(object sender, EventArgs e)
        {
            this.btnAttack.Enabled = true;
            this.btnDefend.Enabled = true;
            this.btnFlee.Enabled = true;
        }
    }
}
